package NW_MC;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.text.html.HTMLDocument.Iterator;

import NWPackage.Cell;
import NWPackage.PairPreferdCandidateCell;


public class MCEntropyMatrix {
	
	//Map <Candidate, Entropy calculations Values>
	public Map<String,MCEntropyCell> MCEntropys;
	
	
	public MCEntropyMatrix(List<String> optionalWinners)
	{
		MCEntropys = new HashMap<String, MCEntropyCell>();
		
		for (int i = 0; i < optionalWinners.size(); i++) {
			String optionalWinner = optionalWinners.get(i);
			MCEntropys.put(new String(optionalWinner),new MCEntropyCell(optionalWinner));
		}
	}
	
	public Map<String, MCEntropyCell> getMCEntropys() {
		return MCEntropys;
	}
	
	public String stringIt(){
		String s = "";		 			 
		for (Map.Entry<String,MCEntropyCell> entry : MCEntropys.entrySet() ) {
			s = s +  entry.getValue().StringIt();
		}
		return s;
	}
	
	
	public void increaseCandidateWinner(String candidateWinnerName) throws Exception
	{
		MCEntropyCell winnerCell = findCandidate(candidateWinnerName);
		try{
			winnerCell.addWin();
		}
		catch(Exception e)
		{
			throw e;
		}
	}
	//for full Monte Carlo
	public void increaseCandidateWinner(String candidateWinnerName,double probability) throws Exception {
		MCEntropyCell winnerCell = findCandidate(candidateWinnerName);
		try{
			winnerCell.addWin(probability);
		}
		catch(Exception e)
		{
			throw e;
		}
		
	}
	
	private MCEntropyCell findCandidate(String candidateWinnerName) {
		return this.MCEntropys.get(candidateWinnerName);
	}
	public void clear()
	{
		this.MCEntropys.clear();
	}
	
	/*Lihi's addition - returns the max prob and not an entropy*/
	public double calcProbability(double assumptionProbability){
		double prob = 0;
		for (MCEntropyCell cell : MCEntropys.values()) {			
			double p=cell.calcProbability();
			if (p>prob)
				prob = p;
		}
		return prob* assumptionProbability;
	}
	
	
	public double calcWeightedEntropy(double assumptionProbability, double fullEntropy)throws Exception {
		double sumEntropy = 0;
		for (MCEntropyCell cell : MCEntropys.values()) {
			sumEntropy+=cell.calcEntropy();
		}
		
		double ans = 0.0;
		if (fullEntropy == 0.0) //full entropy calc
			ans = (-1.0)*sumEntropy * assumptionProbability;
		else	//query entropy-Gain calc
			ans =  (fullEntropy - ((-1.0)*sumEntropy)) * assumptionProbability;
		return ans;
	}
	public double calcFullWeightedEntropy(double assumptionProbability) {
		double sumEntropy = 0;
		for (MCEntropyCell cell : MCEntropys.values()) {
			sumEntropy+=cell.calcFullEntropy();
		}
		return (-1.0)*sumEntropy * assumptionProbability;
	}
	
	private String getLoser() {
		int minWons = Integer.MAX_VALUE;
		String loserCand = "";
		for (MCEntropyCell cell : MCEntropys.values()) {
			if (cell.numOfMCruns < minWons)
			{
				minWons = cell.numOfMCruns;
				loserCand = cell.candidateName;
			}
		}
		return loserCand;
	} 
	
	public String getWinner()
	{
		int maxWons = -1;
		String winnerCand = "";
		for (MCEntropyCell cell : MCEntropys.values()) {
			if (cell.numOfMCruns > maxWons)
			{
				maxWons = cell.numOfMCruns;
				winnerCand = cell.candidateName;
			}
		}
		return winnerCand;
	}
	
	private String getSecondWinner() {
		int maxWons = Integer.MIN_VALUE;
		int secondWonNumber = Integer.MIN_VALUE;
		String secondName = "";
		String winnerName = "";
		for (MCEntropyCell cell : MCEntropys.values()) {
			if (cell.numOfMCruns > maxWons)
			{
				secondWonNumber = maxWons;
				maxWons = cell.numOfMCruns;
				secondName = winnerName;
				winnerName = cell.candidateName;
				
			}
			else if (cell.numOfMCruns > secondWonNumber){
				secondWonNumber = cell.numOfMCruns;
				secondName = cell.candidateName;
			}
		}
		return secondName;
	}
	
	public boolean isContainWinner(Cell assumption) {
		return ((PairPreferdCandidateCell)assumption).isContain(this.getWinner()); 
	}
	
	public boolean isContainPreferredWinner(Cell assumption) {
		return ((PairPreferdCandidateCell)assumption).isContainPreferred(this.getWinner()); 
	}
	
	public boolean isContainLoser(Cell assumption) {
		return ((PairPreferdCandidateCell)assumption).isContain(this.getLoser());
	}
	
	public boolean isContainSecondWinner(Cell assumption) {
		return ((PairPreferdCandidateCell)assumption).isContain(this.getSecondWinner());
	}
	
	
	
}
